/*
 * RT MAP, Home of Professional MAP
 * Copyright 2020/7/6 Bit Main Inc. and/or its affiliates and other contributors
 * as indicated by the @author tags. All rights reserved.
 * See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 */
package com.mz.springbootdemo.common.utils;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Description: Redis工具类
 * @author 盟主
 * @package RedisUtils
 * @date 2022/2/24 10:24 上午
*/
@SuppressWarnings("ALL")
@Component("redisUtils")
public class RedisUtils {
    @Autowired
    private JedisPool jedisPool;

    interface CacheExecutor<T> {
        T execute(Jedis jedis);
    }

    private <T> T execute(CacheExecutor<T> executor) {
        T result;
        Jedis jedis = jedisPool.getResource();
        try {
            result = executor.execute(jedis);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return result;
    }

    /**
     * 推送元素到集合List中 在key对应 list的头部添加字符串元素(最左边)
     *
     * @param key   键
     * @param value 值
     * @return 推送后集合内元素个数
     */
    public Long lpush(String key, String... value) {
        return execute(jedis -> jedis.lpush(key, value));
    }

    /**
     * 推送元素到集合List中 在key对应 list的尾部添加字符串元素 (最右边)
     *
     * @param key   键
     * @param value 值
     * @return java.lang.Long
     * @author 盟主
     * @date 2018/11/8 14:46
     */
    public Long rpush(String key, String... value) {
        return execute(jedis -> jedis.rpush(key, value));
    }

    /**
     * 移除并返回列表的第一个元素
     *
     * @param key 键
     * @return java.lang.String
     * @author 盟主
     * @date 2018/12/11 14:55
     */
    public String lpop(String key) {
        return execute(jedis -> jedis.lpop(key));
    }

    /**
     * 移除列表的最后一个元素，返回值为移除的元素。
     *
     * @param key 键
     * @return java.lang.String
     * @author 盟主
     * @date 2018/12/11 14:55
     */
    public String rpop(String key) {
        return execute(jedis -> jedis.rpop(key));
    }

    /**
     * 获取所有集合元素
     *
     * @param key 集合的key
     * @return java.util.List<java.lang.String>
     * @author 盟主
     * @date 2018/12/11 14:57
     */
    public List<String> lrange(String key) {
        return execute(jedis -> jedis.lrange(key, 0L, -1L));
    }

    /**
     * 设置给定 key 的值。如果 key 已经存储其他值， SET 就覆写旧值，且无视类型。
     *
     * @param key   键
     * @param value 值
     * @return java.lang.String
     * @author 盟主
     * @date 2018/12/11 14:59
     */
    public String set(final String key, final String value) {
        return execute(jedis -> jedis.set(key, value));
    }

    /**
     * 用于获取指定 key 的值。如果 key 不存在，返回 null 。如果key 储存的值不是字符串类型，返回一个错误。
     *
     * @param key 获取指定 key 的值
     * @return java.lang.String
     * @author 盟主
     * @date 2018/12/11 15:00
     */
    public String get(final String key) {
        return execute(jedis -> jedis.get(key));
    }

    /**
     * 检查给定 key 是否存在
     *
     * @param key key
     * @return java.lang.Boolean
     * @author 盟主
     * @date 2018/12/11 15:04
     */
    public Boolean exists(final String key) {
        return execute(jedis -> jedis.exists(key));
    }

    /**
     * 将 key 的值设为 value ，当且仅当 key 不存在。
     * 若给定的 key 已经存在，则 SETNX 不做任何动作。
     *
     * @param key   key
     * @param value value
     * @return java.lang.Long
     * @author 盟主
     * @date 2018/12/11 15:05
     */
    public Long setnx(final String key, final String value) {
        return execute(jedis -> jedis.setnx(key, value));
    }

    /**
     * 将值 value 关联到 key ，并将 key 的生存时间设为 seconds (以秒为单位)。
     * 如果 key 已经存在， SETEX 命令将覆写旧值。
     *
     * @param key     键
     * @param seconds 过期时间 单位秒
     * @param value   值
     * @return java.lang.String
     * @author 盟主
     * @date 2018/12/11 15:06
     */
    public String setex(final String key, final int seconds, final String value) {
        return execute(jedis -> jedis.setex(key, seconds, value));
    }

    /**
     * 为给定 key 设置生存时间，当 key 过期时(生存时间为 0 )，它会被自动删除。
     *
     * @param key     键
     * @param seconds 过期时间单位秒
     * @return java.lang.Long
     * @author 盟主
     * @date 2018/12/11 15:08
     */
    public Long expire(final String key, final int seconds) {
        return execute(jedis -> jedis.expire(key, seconds));
    }

    /**
     * 用于为 key 设置生存时间。
     * 接受的时间参数是 UNIX 时间戳(unix timestamp)。
     *
     * @param key          键
     * @param milliseconds UNIX 时间戳(unix timestamp) 例如：cache 1355292000  # 这个 key 将在 2012.12.12 过期
     * @return java.lang.Long
     * @author 盟主
     * @date 2018/12/11 15:09
     */
    public Long expireAt(final String key, final int milliseconds) {
        return execute(jedis -> jedis.expireAt(key, milliseconds));
    }

    /**
     * 将 key 中储存的数字值增一。
     * 如果 key 不存在，那么 key 的值会先被初始化为 0 ，然后再执行 INCR 操作。
     * 如果值包含错误的类型，或字符串类型的值不能表示为数字，那么返回一个错误。
     * 本操作的值限制在 64 位(bit)有符号数字表示之内。
     *
     * @param key key
     * @return java.lang.Long
     * @author 盟主
     * @date 2018/12/11 15:10
     */
    public Long incr(final String key) {
        return execute(jedis -> jedis.incr(key));
    }

    /**
     * 将 key 中储存的数字值减一。
     * 如果 key 不存在，那么 key 的值会先被初始化为 0 ，然后再执行 DECR 操作。
     * 如果值包含错误的类型，或字符串类型的值不能表示为数字，那么返回一个错误。
     * 本操作的值限制在 64 位(bit)有符号数字表示之内。
     *
     * @param key 键
     * @return java.lang.Long
     * @author 盟主
     * @date 2018/12/11 15:13
     */
    public Long decr(final String key) {
        return execute(jedis -> jedis.decr(key));
    }

    /**
     * 查看哈希表 key 中，给定域 field 是否存在。
     *
     * @param key   key
     * @param field 字段名
     * @return boolean
     * @author 盟主
     * @date 2018/12/11 15:11
     */
    public boolean hexists(final String key, final String field) {
        return execute(jedis -> jedis.hexists(key, field));
    }

    /**
     * 将哈希表 key 中的域 field 的值设为 value 。
     * 如果 key 不存在，一个新的哈希表被创建并进行 HSET 操作。
     * 如果域 field 已经存在于哈希表中，旧值将被覆盖。
     *
     * @param key   key
     * @param field 域
     * @param value 值
     * @return java.lang.Long
     * @author 盟主
     * @date 2018/12/11 15:14
     */
    public Long hset(final String key, final String field, final String value) {
        return execute(jedis -> jedis.hset(key, field, value));
    }

    /**
     * 只有在字段 field 不存在时，设置哈希表字段的值。
     * 用于为哈希表中不存在的的字段赋值 。
     * 如果哈希表不存在，一个新的哈希表被创建并进行 HSET 操作。
     * 如果字段已经存在于哈希表中，操作无效。
     * 如果 key 不存在，一个新哈希表被创建并执行 HSETNX 命令。
     *
     * @param key   缓存key
     * @param field 域
     * @param value 值
     * @return java.lang.Long
     * @author 盟主
     * @date 2018/12/25 15:16
     */
    public Long hsetnx(final String key, final String field, final String value) {
        return execute(jedis -> jedis.hsetnx(key, field, value));
    }

    /**
     * 同时将多个 field-value (域-值)对设置到哈希表 key 中。
     * 此命令会覆盖哈希表中已存在的域。
     *
     * @param key  key
     * @param hash Map数据
     * @return java.lang.Long
     * @author 盟主
     * @date 2018/12/11 15:14
     */
    public String hmsetMap(final String key, final Map<String, String> hash) {
        return execute(jedis -> jedis.hmset(key, hash));
    }

    /**
     * 返回哈希表 key 中给定域 field 的值。
     *
     * @param key   key
     * @param field 字段名
     * @return java.lang.String
     * @author 盟主
     * @date 2018/12/11 15:16
     */
    public String hget(final String key, final String field) {
        return execute(jedis -> jedis.hget(key, field));
    }

    /**
     * 同时将多个 field-value (域-值)对设置到哈希表 key 中。
     * 此命令会覆盖哈希表中已存在的域。
     *
     * @param key
     * @param hash
     * @return java.lang.String
     * @Description 操作map集合 设置值
     * @author 盟主
     * @date 2018/11/8 14:50
     */
    public String hmset(final String key, final Map<String, String> hash) {
        return execute(jedis -> jedis.hmset(key, hash));
    }

    /**
     * 根据指定key获取map集合里面的值
     *
     * @param key
     * @param fields
     * @return java.util.List<java.lang.String>
     * @author 盟主
     * @date 2018/11/8 14:51
     */
    public List<String> hmget(final String key, final String... fields) {
        return execute(jedis -> jedis.hmget(key, fields));
    }

    /**
     * 删除给定的一个key 。不存在的 key 会被忽略。
     *
     * @param key key
     * @return java.lang.Long
     * @author 盟主
     * @date 2018/12/11 15:17
     */
    public Long del(final String key) {
        return execute(jedis -> jedis.del(key));
    }

    /**
     * 删除哈希表 key 中的一个或多个指定域，不存在的域将被忽略。
     *
     * @param key   key
     * @param field 动态数据可以指定多个域
     * @return java.lang.Long
     * @author 盟主
     * @date 2018/12/11 15:19
     */
    public Long hdel(final String key, final String... field) {
        return execute(jedis -> jedis.hdel(key, field));
    }

    /**
     * 返回哈希表 key 中，所有的域和值。
     * 在返回值里，紧跟每个域名(field name)之后是域的值(value)，所以返回值的长度是哈希表大小的两倍。
     *
     * @param key key
     * @return java.util.Map<java.lang.String                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               ,                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               java.lang.String> 以列表形式返回哈希表的域和域的值。 若 key 不存在，返回空列表。
     * @author 盟主
     * @date 2018/12/11 15:21
     */
    public Map<String, String> hgetAll(final String key) {
        return execute(jedis -> jedis.hgetAll(key));
    }

    /**
     * 为哈希表 key 中的域 field 的值加上增量+1。
     * 增量也可以为负数，相当于对给定域进行减法操作。
     * 如果 key 不存在，一个新的哈希表被创建并执行 HINCRBY 命令。
     * 如果域 field 不存在，那么在执行命令前，域的值被初始化为 0 。
     * 对一个储存字符串值的域 field 执行 HINCRBY 命令将造成一个错误。
     * 本操作的值被限制在 64 位(bit)有符号数字表示之内。
     *
     * @param key   key
     * @param field 域
     * @return java.lang.Long
     * @author 盟主
     * @date 2018/12/11 15:22
     */
    public Long hincrby(final String key, String field) {
        return hincrby(key, field, 1);
    }

    /**
     * 将 key 所储存的值减去减量 -1 。
     * 如果 key 不存在，那么 key 的值会先被初始化为 0 ，然后再执行 DECRBY 操作。
     * 如果值包含错误的类型，或字符串类型的值不能表示为数字，那么返回一个错误。
     * 本操作的值限制在 64 位(bit)有符号数字表示之内。
     *
     * @param key   key
     * @param field 域
     * @return java.lang.Long
     * @author 盟主
     * @date 2018/12/11 15:24
     */
    public Long decrby(final String key, String field) {
        return hincrby(key, field, -1);
    }

    /**
     * 为哈希表 key 中的域 field 的值加上增量指定value 。
     * 增量也可以为负数，相当于对给定域进行减法操作。
     * 如果 key 不存在，一个新的哈希表被创建并执行 HINCRBY 命令。
     * 如果域 field 不存在，那么在执行命令前，域的值被初始化为 0 。
     * 对一个储存字符串值的域 field 执行 HINCRBY 命令将造成一个错误。
     * 本操作的值被限制在 64 位(bit)有符号数字表示之内。
     *
     * @param key   key
     * @param field 域
     * @param value 增量值
     * @return java.lang.Long
     * @author 盟主
     * @date 2018/12/11 15:25
     */
    public Long hincrby(final String key, String field, long value) {
        return execute(jedis -> jedis.hincrBy(key, field, value));
    }

    /**
     * 以秒为单位，返回给定 key 的剩余生存时间(TTL, time to live)。
     *
     * @param key key
     * @return java.lang.Long
     * @author 盟主
     * @date 2018/12/11 15:28
     */
    public Long ttl(final String key) {
        return execute(jedis -> jedis.ttl(key));
    }

    /**
     * 返回哈希表 key 中所有域的值
     *
     * @param key key
     * @return java.util.List<java.lang.String>
     * @author 盟主
     * @date 2018/12/11 15:29
     */
    public List<String> hvals(final String key) {
        return execute(jedis -> jedis.hvals(key));
    }

    /**
     * 查找所有符合给定模式 pattern 的 key 。
     * KEYS * 匹配数据库中所有 key 。
     * KEYS h?llo 匹配 hello ， hallo 和 hxllo 等。
     * KEYS h*llo 匹配 hllo 和 heeeeello 等。
     * KEYS h[ae]llo 匹配 hello 和 hallo ，但不匹配 hillo 。
     * 特殊符号用 \ 隔开
     *
     * @param key key
     * @return java.util.Set<java.lang.String>
     * @author 盟主
     * @date 2018/12/11 15:30
     */
    public Set<String> keys(final String key) {
        return execute(jedis -> jedis.keys(key));
    }

    /**
     * 将 key 的值设为 value ，当且仅当 key 不存在。
     * 若给定的 key 已经存在，则 SETNX 不做任何动作。
     *
     * @param key   key
     * @param value value
     * @return java.lang.Long
     * @author 盟主
     * @date 2018/12/11 15:05
     */
    public Long setNx(final String key, final String value) {
        return execute(jedis -> jedis.setnx(key, value));
    }

    /**
     * 将给定 key 的值设为 value ，并返回 key 的旧值(old value)。
     * 当 key 存在但不是字符串类型时，返回一个错误。
     *
     * @param key   key
     * @param value value
     * @return java.lang.String
     * @author 盟主
     * @date 2018/12/11 15:32
     */
    public String getSet(final String key, final String value) {
        return execute(jedis -> jedis.getSet(key, value));
    }

}
